/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.karol.lx.main;

import java.io.*;
import java.net.*;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author karol
 */
public class StateManager implements Runnable {

    private static StateManager instance = null;
    private Timer mMainTimer;
    private Thread mListenerThread;
    private Date mStartTime;
    private DatagramSocket mSenderSocket;
    private MulticastSocket mListenerSocket;
    private int mState;
    public static final int STATE_PRIMARY = 0;
    public static final int STATE_SECONDARY = 1;
    public static int MULTICAST_PORT = 33033;
    public static String MULTICAST_GROUP = "225.0.0.20";
    private long mOldestAge = 0;

    private StateManager() {
        mMainTimer = new Timer();
        mStartTime = new Date(Calendar.getInstance().getTimeInMillis());
        try {
            mSenderSocket = new DatagramSocket();
            mListenerSocket = new MulticastSocket(MULTICAST_PORT);
            mListenerSocket.joinGroup(InetAddress.getByName(MULTICAST_GROUP));
        } catch (IOException ex) {
            Logger.getLogger(StateManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        mListenerThread = new Thread(this);
        mState = STATE_SECONDARY;
    }

    public int getState() {
        return mState;
    }

    public synchronized static StateManager getInstance() {
        if (instance == null) {
            instance = new StateManager();
        }
        return instance;
    }

    public void main() {
        mMainTimer.scheduleAtFixedRate(new TimerTask() {

            @Override
            public void run() {
                broadcastAge();
            }
        }, 0, 20000);
        mListenerThread.start();
    }

    protected void broadcastAge() {
        long tAge = Calendar.getInstance().getTimeInMillis() - mStartTime.getTime();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(stream);
        try {
            if (tAge > mOldestAge)
                mState = STATE_PRIMARY;
            dos.writeLong(tAge);
            mSenderSocket.send(new DatagramPacket(stream.toByteArray(), stream.toByteArray().length, InetAddress.getByName(MULTICAST_GROUP), MULTICAST_PORT));
            Logger.getLogger(StateManager.class.getName()).log(Level.INFO, "State : " + getState());
        } catch (IOException ex) {
            Logger.getLogger(StateManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void run() {
        byte[] buff = new byte[10];
        DatagramPacket tPacket = new DatagramPacket(buff, buff.length);

        while (true) {
            try {
                mListenerSocket.receive(tPacket);

                if (!tPacket.getAddress().equals(InetAddress.getLocalHost())) {
                    ByteArrayInputStream stream = new ByteArrayInputStream(buff);
                    DataInputStream dis = new DataInputStream(stream);
                    long tReceivedAge = dis.readLong();
                    if (tReceivedAge > mOldestAge)
                        mOldestAge = tReceivedAge;
                }

            } catch (IOException ex) {
                Logger.getLogger(StateManager.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}
